#include "NeoSpinBoxStyle.h"
#include "def.h"
#include <QPainter>
#include <QStyleOption>

NeoSpinBoxStyle::NeoSpinBoxStyle(QStyle *style)
    : QProxyStyle(style)
{
}

NeoSpinBoxStyle::~NeoSpinBoxStyle() = default;

void NeoSpinBoxStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
{
    switch (control)
    {
    case CC_SpinBox:
    {
        if (const QStyleOptionSpinBox *spinBoxOption = qstyleoption_cast<const QStyleOptionSpinBox *>(option))
        {
            const int borderRadius = 5;
            const int lineRadius = 1;

            painter->save();
            painter->setPen(Qt::NoPen);
            painter->setBrush(Qt::NoBrush);
            painter->setRenderHint(QPainter::Antialiasing);
            QRect addLineRect = subControlRect(control, spinBoxOption, SC_ScrollBarAddLine, widget).adjusted(NEO_RADIUS_ADJUSTED_VALUES);
            QRect subLineRect = subControlRect(control, spinBoxOption, SC_ScrollBarSubLine, widget).adjusted(NEO_RADIUS_ADJUSTED_VALUES);
            painter->setBrush(Qt::lightGray);
            painter->drawRoundedRect(addLineRect, borderRadius, borderRadius);
            painter->drawRoundedRect(subLineRect, borderRadius, borderRadius);
            if (spinBoxOption->activeSubControls & SC_ScrollBarAddLine)
            {
                if (spinBoxOption->state & QStyle::State_MouseOver)
                {
                    painter->setBrush(Qt::gray);
                }
                painter->drawRoundedRect(addLineRect, borderRadius, borderRadius);
            }
            else if (spinBoxOption->activeSubControls & SC_ScrollBarSubLine)
            {
                if (spinBoxOption->state & QStyle::State_MouseOver)
                {
                    painter->setBrush(Qt::gray);
                }
                painter->drawRoundedRect(subLineRect, borderRadius, borderRadius);
            }

            QRect editFieldRect = subControlRect(control, spinBoxOption, SC_SpinBoxEditField, widget);
            QRect lineRect = editFieldRect.adjusted(0, editFieldRect.height(), 0, 2 * lineRadius);
            if (spinBoxOption->state & QStyle::State_HasFocus)
            {
                painter->setPen(Qt::blue);
                painter->setBrush(Qt::blue);
            }
            else
            {
                painter->setPen(Qt::gray);
                painter->setBrush(Qt::gray);
            }
            painter->drawRoundedRect(lineRect, lineRadius, lineRadius);

            painter->setPen(Qt::black);
            painter->setFont(QFont("Font Awesome 6 Free Solid"));
            painter->drawText(addLineRect, Qt::AlignCenter, QChar((unsigned short)NeoIconType::FontAwesomeSolid::Plus));
            painter->drawText(subLineRect, Qt::AlignCenter, QChar((unsigned short)NeoIconType::FontAwesomeSolid::Minus));
            painter->restore();
            return;
        }
        break;
    }
    default:
        break;
    }
    QProxyStyle::drawComplexControl(control, option, painter, widget);
}

QRect NeoSpinBoxStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
                                      SubControl subControl, const QWidget *widget) const
{
    QRect spinBoxRect = QProxyStyle::subControlRect(control, option, SC_SpinBoxFrame, widget);
    switch (subControl)
    {
    case SC_ScrollBarAddLine:
    {
        return QRect(spinBoxRect.width() - spinBoxRect.height(), 0, spinBoxRect.height(), spinBoxRect.height());
    }
    case SC_ScrollBarSubLine:
    {
        return QRect(0, 0, spinBoxRect.height(), spinBoxRect.height());
    }
    case SC_SpinBoxEditField:
    {
        return QRect(spinBoxRect.height(), 0, spinBoxRect.width() - 2 * spinBoxRect.height(), spinBoxRect.height() - 4 * NEO_RADIUS_ADJUSTED_VALUE);
    }
    default:
        break;
    }
    return QProxyStyle::subControlRect(control, option, subControl, widget);
}

QStyle::SubControl NeoSpinBoxStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const
{
    if (subControlRect(control, option, SC_ScrollBarAddLine, widget).contains(pos))
    {
        return SC_ScrollBarAddLine;
    }
    else if (subControlRect(control, option, SC_ScrollBarSubLine, widget).contains(pos))
    {
        return SC_ScrollBarSubLine;
    }
    else if (subControlRect(control, option, SC_SpinBoxEditField, widget).contains(pos))
    {
        return SC_SpinBoxEditField;
    }
    return QProxyStyle::hitTestComplexControl(control, option, pos, widget);
}
